Skip to content

seo: add SoftwareApplication schema on homepage, enterprise, pricing, features#4821

Merged
vfanucci merged 4 commits into
mainfrom
schema-software-application
Jun 8, 2026
Merged

seo: add SoftwareApplication schema on homepage, enterprise, pricing, features#4821
vfanucci merged 4 commits into
mainfrom
schema-software-application

Conversation

@vfanucci

Copy link
Copy Markdown
Contributor

Summary

Adds a reusable SchemaSoftwareApplication.astro component and injects it on the four highest-traffic product pages: homepage, enterprise, pricing, and features.

Identified as priority 1 in the Agents Taskforce Pillar 1 audit — current site only emits Organization + WebSite (homepage) / BreadcrumbList schema. Without SoftwareApplication, AI agents and crawlers have to infer that Kestra is a software product instead of reading it directly.

What the schema declares

  • @type: SoftwareApplication (+ @id: https://kestra.io/#software)
  • applicationCategory: DeveloperApplication, applicationSubCategory: Workflow Orchestration
  • operatingSystem, license (Apache 2.0), downloadUrl (GitHub repo)
  • author / publisher references the existing Organization @id from layout.astro (clean graph linkage)
  • offers: three tiers — Open Source (free), Cloud (pay-as-you-go), Enterprise (contact sales)
  • Per-page name / description / url overrides to match page positioning

Files

  • src/components/common/SchemaSoftwareApplication.astro — new reusable component
  • src/pages/index.astro, src/pages/enterprise/index.astro, src/pages/pricing/index.astro, src/pages/features/index.astro — inject via existing <Fragment slot="head"> pattern (same as pricingSchema)

Test plan

  • Build site locally and confirm no Astro errors
  • Run https://search.google.com/test/rich-results on the 4 deployed URLs to confirm valid SoftwareApplication markup
  • Re-run the agent-readiness audit and confirm SoftwareApplication is detected on all 4 pages

… features

Adds a reusable SchemaSoftwareApplication.astro component and injects it
on the four highest-traffic product pages. Gives AI agents and search
crawlers a machine-parseable description of Kestra as a software product,
including category, license, supported platforms, and offers per tier.

Identified as priority 1 in the Agents Taskforce Pillar 1 audit.
@github-actions

github-actions Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

## 🔦 Lighthouse Benchmark

Tested: https://ks-schema-software-application-docs.kestra-io.workers.dev on 2026-06-08 08:58 UTC
No baseline available — scores will appear after the first merge to main

Scores (0–100, higher is better)

Page Performance Accessibility Best Practices SEO
Home 77 83 56 92
Pricing 98 91 56 100
Enterprise 96 82 56 100
Cloud 92 87 56 100
About Us 83 91 56 100
Docs Landing 93 88 56 92
Contribute to Kestra (simple docs) 98 88 56 92
Flow (full featured docs) 90 90 56 92
Blog Index 67 91 56 100
Blog Post (sample) 97 87 56 100
VS Page (sample) 98 88 56 100
Plugins Landing 90 81 56 92
Plugin Page (sample) 94 87 56 100
Plugin Debug Page (sample) 94 87 56 100
Plugin Debug Return Page (sample) 91 88 56 100
Blueprints Landing 89 80 56 92
Blueprint Audit Logs CSV Export 67 86 56 100

Core Web Vitals (lower is better)

Page LCP FCP TBT CLS Speed Index
Home 1.57 s 0.73 s 316 ms 0.002 2.06 s
Pricing 1.08 s 0.59 s 25 ms 0.000 0.90 s
Enterprise 1.40 s 0.63 s 29 ms 0.000 0.89 s
Cloud 1.88 s 0.57 s 7 ms 0.000 0.83 s
About Us 2.95 s 0.67 s 15 ms 0.000 0.89 s
Docs Landing 1.66 s 0.69 s 66 ms 0.000 1.03 s
Contribute to Kestra (simple docs) 0.95 s 0.68 s 32 ms 0.000 0.88 s
Flow (full featured docs) 1.89 s 0.59 s 103 ms 0.000 1.17 s
Blog Index 3.69 s 1.10 s 100 ms 0.000 28.57 s
Blog Post (sample) 1.25 s 0.57 s 6 ms 0.000 0.82 s
VS Page (sample) 1.18 s 0.52 s 9 ms 0.005 0.71 s
Plugins Landing 1.13 s 0.57 s 66 ms 0.000 2.97 s
Plugin Page (sample) 0.93 s 0.56 s 32 ms 0.051 2.20 s
Plugin Debug Page (sample) 0.94 s 0.50 s 97 ms 0.001 2.07 s
Plugin Debug Return Page (sample) 1.13 s 0.56 s 126 ms 0.025 2.33 s
Blueprints Landing 1.68 s 0.90 s 30 ms 0.000 1.93 s
Blueprint Audit Logs CSV Export 1.04 s 0.62 s 196 ms 0.485 2.25 s
Legend

🟢 improved  ·  🔻 regressed  ·  (blank) no significant change
Score threshold: ±10 pts  ·  Metric threshold: ±30% of baseline

☁️ Cloudflare Worker Preview Deployed!

🔗 https://ks-schema-software-application-docs.kestra-io.workers.dev
🔗 https://618425e2-docs.kestra-io.workers.dev

@vfanucci vfanucci requested a review from Piyush-r-bhaskar May 27, 2026 10:23
"applicationCategory": "DeveloperApplication",
"applicationSubCategory": "Workflow Orchestration",
"operatingSystem": "Linux, macOS, Windows, Docker, Kubernetes",
"softwareVersion": "1.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this version ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bien vu, c'était une valeur statique inventée. Retirée dans 1b4e115softwareVersion est optionnel sur SoftwareApplication et mieux vaut l'omettre que de servir une fausse info qui se désynchronise à chaque release.

@@ -1,5 +1,6 @@
---
import Layout from "~/components/layout.astro"
import SchemaSoftwareApplication from "~/components/common/SchemaSoftwareApplication.astro"

import Hero from "~/components/enterprise/Hero.vue"
import SeeHow from "~/components/common/SeeHow.astro"

@Piyush-r-bhaskar Piyush-r-bhaskar May 27, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might know better. is it good for Crawlers ?

Identical @id, 4 different url values, 2 different name s. To a JSON-LD parser this would be one entity with four contradictory definitions. no ?

page id name url
home https://kestra.io/#software Kestra https://kestra.io
enterprise https://kestra.io/#software Kestra Enterprise Edition https://kestra.io/enterprise
features https://kestra.io/#software Kestra https://kestra.io/features
pricing https://kestra.io/#software Kestra https://kestra.io/pricing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Très juste, c'était une vraie collision JSON-LD. Fix dans 1b4e115 :

  • SchemaSoftwareApplication accepte maintenant un prop id (par défaut #software) et isVariantOf.
  • /enterprise déclare désormais une entité distincte @id=https://kestra.io/#enterprise-edition avec isVariantOf: { @id: https://kestra.io/#software } → un parser voit deux entités liées (produit principal + variante Enterprise), plus de conflit.
  • Composant retiré de /pricing (le pricingSchema Product+Offer existant couvre déjà la page) et /features (rien d'unique à déclarer).

Résultat :

page @id name
/ #software Kestra
/enterprise #enterprise-edition (isVariantOf → #software) Kestra Enterprise Edition
/pricing — (Product/Offer schema déjà en place)
/features

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still dumb in FR language 😜. I can understand English well 🙂

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oups sorry, it was Claude in French !

…review)

- Make SchemaSoftwareApplication @id parameterizable via prop (default
  remains #software for the home page).
- Enterprise page now declares a distinct entity @id=#enterprise-edition
  with isVariantOf -> #software, so JSON-LD parsers no longer see four
  contradictory definitions sharing the same @id.
- Remove the component from /pricing (already covered by the page-level
  Product+Offer pricingSchema) and /features (no unique entity to declare).
- Drop the hardcoded "softwareVersion": "1.0" — stale value that drifts
  from the real Kestra release. Field is optional and best omitted.
- Tighten operatingSystem to actual OSes (Linux, macOS, Windows). Docker
  and Kubernetes are deployment targets, not operating systems.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…twareApplication; add to /features

The previous decision to leave the existing Product+Offer block on /pricing
was based on the assumption it already covered the page. Google Rich
Results Test shows otherwise: the Product schema triggers Merchant Listing
validation rules (image, priceValidUntil, hasMerchantReturnPolicy,
shippingDetails), producing 6 errors — none of which apply to a SaaS
pricing page.

- /pricing: drop the inline pricingSchema (3x Product) and emit the
  canonical #software entity via SchemaSoftwareApplication. The component's
  built-in offers array already declares all three tiers (Open Source,
  Cloud, Enterprise), so no information is lost and Google validates
  cleanly under SoftwareApplication rules.
- /features: add SchemaSoftwareApplication so the page is no longer
  schema-silent (was only emitting BreadcrumbList + Organization).
- Component: bump default description from "1200+ plugins" to "1400+
  plugins" to match the live homepage copy.

Completes the original PR scope (homepage + enterprise + pricing +
features) and eliminates the Merchant Listing validation errors.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@vfanucci

vfanucci commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Two-step fix recap for @Piyush-r-bhaskar

1. @id collision (commit 1b4e1153d)

  • SchemaSoftwareApplication now accepts an id prop (defaults to #software) and isVariantOf.
  • /enterprise declares a distinct entity @id=https://kestra.io/#enterprise-edition with isVariantOf: { @id: "https://kestra.io/#software" } → parsers see two linked entities (canonical product + Enterprise variant) instead of four contradictory definitions sharing one @id.

2. Product schema on /pricing (commit 00cd319bc)

The original justification for removing the component from /pricing and /features ("pricingSchema Product+Offer already covers the page", "nothing unique to declare on features") turned out to be wrong. The Google Rich Results Test reported 6 validation errors on /pricing:

  • 3 "Product snippet" errors (missing image, aggregateRating/review)
  • 3 "Merchant listing" errors (missing image, priceValidUntil, hasMerchantReturnPolicy, shippingDetails)

These rules apply because Google treats Product as e-commerce inventory — none of those fields are meaningful for a SaaS pricing page.

Fix:

  • /pricing: replaced the inline pricingSchema (3× Product) with <SchemaSoftwareApplication url="https://kestra.io/pricing" />. The component's built-in offers array already declares all three tiers (Open Source, Cloud, Enterprise), so no information is lost and the page validates cleanly under SoftwareApplication rules.
  • /features: added <SchemaSoftwareApplication url="https://kestra.io/features" /> so the page is no longer schema-silent (previously only BreadcrumbList + Organization).
  • Component: bumped default description from "1200+ plugins" → "1400+ plugins" to match the live homepage copy.

Final state

Page @id name
/ #software Kestra
/enterprise #enterprise-edition (isVariantOf#software) Kestra Enterprise Edition
/pricing #software (canonical, with 3 offers) Kestra
/features #software (canonical) Kestra

/pricing and /features re-emit the canonical #software entity with identical core fields, which is fine for graph consolidation — same entity, page-scoped url override.

Test plan once merged: re-run Rich Results Test on the four URLs to confirm 0 errors and SoftwareApplication detection on all four.

…cation

# Conflicts:
#	src/pages/pricing/index.astro
@vfanucci

vfanucci commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 1b4e115

@vfanucci vfanucci merged commit 1e6394c into main Jun 8, 2026
7 checks passed
@vfanucci vfanucci deleted the schema-software-application branch June 8, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants